using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TaxiScript : MonoBehaviour
{
    // 起始检查点
    public Transform startCheckpoint;
    // 结束检查点
    public Transform endCheckpoint;
    // 最佳路线
    public List<Transform> bestRoute;
    // 正在计算路径的协程数量。如果为0，则表示脚本未在计算。这可以帮助你检查脚本何时完成计算。
    [Tooltip("正在运行的计算路径的协程数量。如果为0，则表示脚本未在计算。这可以帮助你检查脚本何时完成计算。")]
    public int coroutines = 0;
    // 每个协程将处理的检查点数量。增加此数量可以根据你的电脑配置使游戏运行变慢，但它会更快地计算出最佳路线。
    [Tooltip("每个协程将处理的检查点数量。增加此数量可以根据你的电脑配置使游戏运行变慢，但它会更快地计算出最佳路线。")]
    public int iterations = 100;
    // 车辆AI控制器
    private CarAIController controller;
    
    // 在第一帧更新之前调用
    void Start()
    {
        // 获取车辆AI控制器组件
        controller = GetComponent<CarAIController>();

        // 如果出租车模式未启用，输出警告
        if(!controller.taxiMode)
        {
            Debug.LogWarning("请确保在CarAIController中启用出租车模式，以便车辆能够按照路径行驶。");
        }

        // 如果车辆未由AI控制，输出警告
        if(!controller.isCarControlledByAI)
        {
            Debug.LogWarning("请确保在CarAIController中启用isCarControlledByAI，以便车辆能够按照路径行驶。");
        }

        // 如果检查点搜索未启用，输出警告
        if(!controller.CheckPointSearch)
        {
            Debug.LogWarning("请确保在CarAIController中启用CheckPointSearch，以便车辆能够按照路径行驶。");
        }

        // 如果未找到控制器，输出错误
        if(!controller)
        {
            Debug.LogError("游戏对象 " + gameObject.name + " 不包含CarAIController脚本。");
        }
    }

    // 计算路线
    public void ComputeRoute()
    {
        // 创建一个包含起始检查点的路线列表
        List<Transform> route = new List<Transform>() {startCheckpoint};

        // 启动协程
        StartCoroutine(Run(route));
        coroutines++;
    }

    // 检查对象是否存在于列表中
    private bool objectExistsInList(List<Transform> list, Transform obj)
    {
        for(int i = 0; i < list.Count; i++)
        {
            if(list[i] == obj)
            {
                return true;
            }
        } 
        return false;
    }

    // 运行协程
    IEnumerator Run(List<Transform> route)
    {
        // 当前检查点
        Transform current = route[route.Count - 1];
        // 当前检查点的脚本
        CheckpointScript script = current.gameObject.GetComponent<CheckpointScript>();

        // 运行标志
        bool run = true;

        // 如果当前检查点的下一个检查点数量大于1，停止运行
        if(script.nextCheckpoints.Count > 1)
        {
            run = false;
        }

        int iterationCount = 0;

        // 循环直到找到终点
        while(run)
        {
            iterationCount++;

            // 每100次迭代暂停一次，以避免阻塞
            if(iterationCount % 100 == 0)
            {
                yield return 0;
            }

            // 获取当前检查点
            current = route[route.Count - 1];
            script = current.gameObject.GetComponent<CheckpointScript>();
            
            // 如果当前检查点有下一个检查点，移动到下一个检查点
            if(script.nextCheckpoints.Count != 0)
            {
                current = script.nextCheckpoints[0];
                script = current.gameObject.GetComponent<CheckpointScript>();
            }

            // 如果到达终点，添加到路线并更新最佳路线
            if(current == endCheckpoint)
            {
                route.Add(current);

                if(bestRoute.Count == 0 || route.Count < bestRoute.Count)
                {
                    bestRoute = new List<Transform>(route);
                }

                coroutines--;
                yield break;
            }

            // 如果没有下一个检查点，停止运行
            if(script.nextCheckpoints.Count == 0)
            {
                coroutines--;
                yield break;
            }

            // 如果下一个检查点数量大于1，停止运行
            if(script.nextCheckpoints.Count > 1)
            {
                break;
            }

            route.Add(current);
        }

        // 获取下一个检查点列表
        List<Transform> next = route[route.Count - 1].GetComponent<CheckpointScript>().nextCheckpoints;

        // 遍历下一个检查点
        for(int i = 0; i < next.Count; i++)
        {
            // 创建当前路线的副本
            List<Transform> localRoute = new List<Transform>(route);
            // 如果下一个检查点不在当前路线中，添加并启动新协程
            if(!objectExistsInList(localRoute, next[i]))
            {
                localRoute.Add(next[i]);
                StartCoroutine(Run(localRoute));
                coroutines++;
            }
        }

        coroutines--;
    }
}